package ngamejava2;

import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.image.BufferedImage;
import java.awt.image.VolatileImage;
import java.io.IOException;
import java.util.ArrayList;
import javax.xml.xpath.XPathExpressionException;
import org.w3c.dom.Node;

public class TiledBackgroundPlane extends ParallaxGamePlane
{
	static final int TILE_WIDTH = 250;
	private String fileName;
	private float offsetLeft;
	private float offsetTop;
	private ArrayList<BackgroundTile> tiles;

	public TiledBackgroundPlane()
	{
		this(0, "");
	}

	public TiledBackgroundPlane(float distance, String bgFileName)
	{
		super(distance);
		try
		{
			this.fileName = bgFileName;
			this.offsetLeft = 0;
			this.offsetTop = 0;
			tiles = new ArrayList<BackgroundTile>();
			if (bgFileName != null && !bgFileName.equals(""))
			{
				loadAndExtract(bgFileName);
			}
		} catch (IOException e)
		{
			throw new RuntimeException();
		}
	}

	protected void loadAndExtract(String fn) throws IOException
	{
		if (!fn.equals(""))
		{
			BufferedImage tmp = SystemFacade.getInstance().getImage(fn);
			System.out.println("LOADED " + fn + "  " + tmp.getWidth() + "x" + tmp.getHeight());
			int x = 0;
			int n = tmp.getWidth() / TILE_WIDTH;
			int i = 0;
			for (i = 0; i < n; i++)
			{
				BackgroundTile tile = new BackgroundTile(SystemFacade.getInstance().newImage(TILE_WIDTH, tmp.getHeight()), x);
				tile.src.getGraphics().drawImage(tmp, -x, 0, null);
				tiles.add(tile);
				x += tile.img.getWidth();
				System.out.println("     EXTRACTED " + (i + 1) + "  " + tile.src.getWidth() + "x" + tile.src.getHeight());
			}
			int w = tmp.getWidth() % TILE_WIDTH;
			if (w > 0)
			{
				BackgroundTile tile = new BackgroundTile(SystemFacade.getInstance().newImage(w, tmp.getHeight()), x);
				tile.src.getGraphics().drawImage(tmp, -x, 0, null);
				tiles.add(tile);
				x += tile.img.getWidth();
				System.out.println("     EXTRACTED " + (i + 1) + "  " + tile.src.getWidth() + "x" + tile.src.getHeight());
			}
			getBounds().setRect(0, 0, x, tiles.get(0).src.getHeight());
		}
	}

	@Override
	public void render(Graphics2D g, long currentFrame)
	{
		int x = (int)offsetLeft;
		int i = 0;
		int mx = (int) (getParent().getCamera().x/getDistance()) + (int) getParent().getCamera().width;
		while (x < mx)
		{
			if (x+tiles.get(i).src.getWidth() > (int) (getParent().getCamera().x/getDistance()))
			{
				//do
				//{
				//	tiles.get(i).check();
				g.drawImage(tiles.get(i).src, x, (int)getOffsetTop(), null);
				//} while (tiles.get(i).img.contentsLost());
			}
			x += tiles.get(i).src.getWidth();
			if (++i == tiles.size())
			{
				i = 0;
			}
		}
		super.render(g, currentFrame);
	}

	public float getOffsetLeft()
	{
		return offsetLeft;
	}

	public void setOffsetLeft(float offsetLeft)
	{
		this.offsetLeft = offsetLeft;
	}

	public float getOffsetTop()
	{
		return offsetTop;
	}

	public void setOffsetTop(float offsetTop)
	{
		this.offsetTop = offsetTop;
	}

	@Override
	public void write(GameWriter gw) throws IOException
	{
		super.write(gw);
		gw.write("fileName", fileName);
		gw.write("offsetLeft", offsetLeft);
		gw.write("offsetTop", offsetTop);
	}

	@Override
	public void read(GameReader gr, Node objectNode) throws XPathExpressionException
	{
		try
		{
			super.read(gr, objectNode);
			fileName = gr.readString(objectNode, "string[@name='fileName']");
			offsetLeft = gr.readFloat(objectNode, "float[@name='offsetLeft']");
			offsetTop = gr.readFloat(objectNode, "float[@name='offsetTop']");
			loadAndExtract(fileName);
		} catch (IOException ex)
		{
			throw new RuntimeException(ex);
		}
	}
}

class BackgroundTile
{
	BufferedImage src;
	VolatileImage img;
	int x;

	public BackgroundTile(BufferedImage src, int x)
	{
		this.src = src;
		this.x = x;
		img = SystemFacade.getInstance().newAcceleratedImage(src.getWidth(), src.getHeight());
		img.getGraphics().drawImage(src, 0, 0, null);
	}

	public void check()
	{

		GraphicsConfiguration gc = SystemFacade.getInstance().getGraphicsConfiguration();
		int valCode = img.validate(gc);
		if (valCode == VolatileImage.IMAGE_INCOMPATIBLE)
		{
			img = SystemFacade.getInstance().newAcceleratedImage(src.getWidth(), src.getHeight());
		}
		img.getGraphics().drawImage(src, 0, 0, null);
	}
}